package com.imooc.service.impl;

import com.imooc.exception.SellException;
import com.imooc.service.RedisLock;
import com.imooc.service.SecKillService;
import com.imooc.utils.KeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * redis -- 单线程 -支持高可用， 分布式集群
 * 分布式锁 == 多台机器上多个进程对一个数据进行操作的互斥
 * 相同的productId作为key
 */
@Service
public class SecKillServiceImpl implements SecKillService {

    @Autowired
    private RedisLock redisLock;

    public static final int TIMEOUT = 10 * 1000; //10s

    static Map<String, Integer> products;
    static Map<String, Integer> stock;
    static Map<String, String> orders;

    static {
        /**
         * 模拟多个表， 商品信息表，库存表， 秒杀成功订单表
         */
        products = new HashMap<>();
        stock  = new HashMap<>();
        orders  = new HashMap<>();
        products.put("001",100000);
        stock.put("001", 100000);
    }
    @Override
    public String queryMap(String productId){
        return "跨年活动，黄金特价，限量"
                + products.get(productId)
                + "还剩： "
                + stock.get(productId)
                + " 份"
                + "已经下单成功的用户数量有"
                + orders.size()
                + "人";
    }

    @Override
    public String querySecKillProductInfo(String productId) {
        return this.queryMap(productId);
    }

    @Override
    /**
     * synchronized
     * 慢 -- 粗粒度 -- 有两个商品秒杀同事访问这个方法，
     * 一个几十万， 一个几个，同一阻塞
     * 只适合单点
     * 但是成功抢到的人很多 -- Redis 抢到的人很少。
     */
//     方法1   public synchronized void  orderProductMockDiffUser(String productId) {

    public void  orderProductMockDiffUser(String productId) {
        // 之前加锁
        long time = System.currentTimeMillis() + TIMEOUT;
        if ( !redisLock.lock(productId, String.valueOf(time))){
            throw new SellException(101, "哎呦喂，人太多了，换个姿势试试~~");
        }

        // 1. 查询商品库存， 为0 结束
        int stockNum = stock.get(productId);
        if (stockNum == 0){
            throw new SellException(100, "活动结束");
        }else {
            // 2 下单（模拟不同openid， 不同用户）
            orders.put(KeyUtil.genUniqueKey(), productId);

            // 3  减去库存
            stockNum -= 1;

            try{
                // 处理耗时间
                Thread.sleep(100);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            stock.put(productId, stockNum);
        }

        // 之后解锁
        redisLock.unlock(productId, String.valueOf(time));


    }


}
